var InitMap = function () {
  viewer.scene.moon.show = false
  viewer.scene.fog.enabled = false
  viewer.scene.sun.show = false
  viewer.scene.skyBox.show = false
  viewer.scene.postProcessStages.fxaa.enabled = true //抗锯齿
  viewer._cesiumWidget._supportsImageRenderingPixelated = Cesium.FeatureDetection.supportsImageRenderingPixelated()
  viewer._cesiumWidget._forceResize = true
  if (Cesium.FeatureDetection.supportsImageRenderingPixelated()) {
    var vtxf_dpr = window.devicePixelRatio
    // 适度降低分辨率
    while (vtxf_dpr >= 2.0) {
      vtxf_dpr /= 2.0
    }
    //alert(dpr);
    viewer.resolutionScale = vtxf_dpr
  }
  // viewer.scene.globe.show = false;
  // 版权清理
  viewer.cesiumWidget.creditContainer.style.display = 'none'
  // viewer.imageryLayers.removeAll()
  // viewer.scene.backgroundColor =new Cesium.Color(0.0, 0.0, 0.0, 0.0);
  viewer.scene.globe.baseColor = Cesium.Color.fromCssColorString('rgb(26, 62, 109)')
}

// ! 世界坐标 转换 经纬度
var cartesian3ToLatLng = function (cartesian3) {
  let ellipsoid = viewer.scene.globe.ellipsoid;
  let cartographic = ellipsoid.cartesianToCartographic(cartesian3);
  let lng = Cesium.Math.toDegrees(cartographic.longitude);
  let lat = Cesium.Math.toDegrees(cartographic.latitude);
  let alt = cartographic.height;
  return [lng, lat, alt];
}

// ! 屏幕坐标 转换 世界坐标
var cartesian2ToCartesian3 = function (position) {
  if (!position) return [];
  // 从相机位置通过windowPosition 世界坐标中的像素创建一条射线。返回Cartesian3射线的位置和方向。 
  // 查找射线与渲染的地球表面之间的交点。射线必须以世界坐标给出。返回Cartesian3对象  
  return viewer.scene.globe.pick(viewer.camera.getPickRay(position), viewer.scene);
};

// ! 屏幕坐标 转换 经纬度
var cartesian2ToLatLng = function (position) {
  if (!position) return [];

  let cartesian3 = viewer.scene.globe.pick(viewer.camera.getPickRay(position), viewer.scene)

  let ellipsoid = viewer.scene.globe.ellipsoid;
  let cartographic = ellipsoid.cartesianToCartographic(cartesian3);
  let lng = Cesium.Math.toDegrees(cartographic.longitude);
  let lat = Cesium.Math.toDegrees(cartographic.latitude);
  let alt = cartographic.height;
  return [lng, lat, alt];
}

/**定义数据集**/
var CreateLayer = function (name, isPrimitiveLayer) {
  if (isPrimitiveLayer) {
    var HousePrimitive = viewer.scene.primitives.add(
      new Cesium.ClassificationPrimitive({
        geometryInstances: [],
        classificationType: Cesium.ClassificationType.CESIUM_3D_TILE
      })
    )
    return HousePrimitive
  } else {
    var traceLayer = new Cesium.CzmlDataSource(name) //数据源
    viewer.dataSources.add(traceLayer)
    return traceLayer
  }
}
/**定义billboard集**/
var BillBoardCollectionLayer = (function () {
  function _(positions, layer) {
    this.billboardsCollection = null
    this.labelsCollection = null
    this._init()
  }

  _.prototype._init = function () {
    this.billboardsCollection = viewer.scene.primitives.add(
      new Cesium.BillboardCollection({
        scene: viewer.scene
      })
    )
    this.labelsCollection = viewer.scene.primitives.add(
      new Cesium.LabelCollection({
        scene: viewer.scene
      })
    )
  }
  _.prototype.add = function (option) {
    this.billboardsCollection.add({
      id: option.id,
      position: Cesium.Cartesian3.fromDegrees(option.longitude, option.latitude, option.altitude),
      scale: option.scale ? option.scale : 0.8,
      disableDepthTestDistance: 99000000,
      heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
      verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
      disableDepthTestDistance: Number.POSITIVE_INFINITY,
      scaleByDistance: new Cesium.NearFarScalar(500, 1.0, 2000, 0.7),
      distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
        option.distanceShow[0],
        option.distanceShow[1]
      ),
      image: option.icon, // 图片存储路径,
      type: option.type
    })

    this.labelsCollection.add({
      // font : `bold 12px sans-serif`,
      position: Cesium.Cartesian3.fromDegrees(option.longitude, option.latitude, option.altitude),
      text: option.name,
      font: 'normal 20px MicroSoft YaHei',
      fillColor: new Cesium.Color.fromBytes(0, 0, 0, 255),
      backgroundColor: new Cesium.Color.fromBytes(255, 255, 255, 200),
      showBackground: true,
      scale: 0.8,
      backgroundPadding: new Cesium.Cartesian2(9, 7),
      outlineWidth: 0,
      pixelOffset: new Cesium.Cartesian2(25.0, -6.0),
      pixelOffsetScaleByDistance: new Cesium.NearFarScalar(
        100,
        1.0,
        2000,
        0.6
      ),
      style: Cesium.LabelStyle.FILL_AND_OUTLINE,
      horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
      verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
      scaleByDistance: new Cesium.NearFarScalar(500, 1.0, 2000, 0.6),
      disableDepthTestDistance: Number.POSITIVE_INFINITY,
      distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
        option.distanceShow[0] < 10000 ? option.distanceShow[0] : 10,
        10000
      ),
      heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
    })
  }
  _.prototype.show = function () {
    this.billboardsCollection.show = true
    this.labelsCollection.show = true
  }
  _.prototype.hide = function () {
    this.billboardsCollection.show = false
    this.labelsCollection.show = false
  }
  _.prototype.get = function (id) {
    console.log(this.billboardsCollection)
    var len = this.billboardsCollection.length
    for (var i = 0; i < len; ++i) {
      var b = this.billboardsCollection.get(i);
      if (b.id == id) {
        return b
      }
    }
    return null
  }
  _.prototype.remove = function () {
    viewer.scene.primitives.remove(this.billboardsCollection)
    viewer.scene.primitives.remove(this.labelsCollection)
  }
  return _

})()
/*清除图层内所有数据*/
var LayerRemoveAll = function (dataSources) {
  dataSources.entities.removeAll()
}

var LoadCityROI = function (roi, dataSources) {
  var promise = Cesium.GeoJsonDataSource.load(
    roi
  )
  promise.then(function (dataSource) {
    var entities = dataSource.entities.values
    for (let i = 0; i < entities.length; i++) {
      var arr = entities[i].polygon.hierarchy._value.positions
      var positions = []
      for (var j = 0; j < arr.length; j++) {
        var cartographic = Cesium.Cartographic.fromCartesian(arr[j])
        var currentClickLon = Cesium.Math.toDegrees(cartographic.longitude)
        var currentClickLat = Cesium.Math.toDegrees(cartographic.latitude)

        positions.push(currentClickLon)
        positions.push(currentClickLat)
      }
      var pp = {
        name: "管辖区域",
        polyline: {
          positions: Cesium.Cartesian3.fromDegreesArray(positions),
          clampToGround: true,
          width: 2,
          material: Cesium.Color.fromCssColorString('rgba(255, 255, 255, 0.6)'),
          zIndex: 10
        },
        polygon: {
          hierarchy: {
            positions: Cesium.Cartesian3.fromDegreesArray(positions)
          },
          material: Cesium.Color.fromCssColorString('rgba(213, 226, 246, 0.05)'),
          heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
        }
      }
      dataSources.entities.add(pp);

    }
  })
}
/**加载Geojson**/
var LoadGeoJsonPolygon = function (roi, dataSources, opt) {
  console.log(roi)
  var promise = Cesium.GeoJsonDataSource.load(roi)
  promise.then(function (dataSource) {
    var entities = dataSource.entities.values
    for (let i = 0; i < entities.length; i++) {
      var arr = entities[i].polygon.hierarchy._value.positions
      var positions = []
      for (var j = 0; j < arr.length; j++) {
        var cartographic = Cesium.Cartographic.fromCartesian(arr[j])
        var currentClickLon = Cesium.Math.toDegrees(cartographic.longitude)
        var currentClickLat = Cesium.Math.toDegrees(cartographic.latitude)

        positions.push(currentClickLon)
        positions.push(currentClickLat)
      }
      // 计算polygon中心点
      var polyCenter = Cesium.BoundingSphere.fromPoints(Cesium.Cartesian3.fromDegreesArray(positions)).center; //中心点
      polyCenter = Cesium.Ellipsoid.WGS84.scaleToGeodeticSurface(polyCenter);


      var pp = {
        id: opt.id ? opt.id : entities[i].id,
        name: opt.name ? opt.name : entities[i].name,
        polygon: {
          hierarchy: {
            positions: Cesium.Cartesian3.fromDegreesArray(positions)
          },
          material: opt.color ? Cesium.Color.fromCssColorString(opt.color) : Cesium.Color.fromCssColorString('rgba(213, 226, 246, 0.15)'),
          heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
        }
      }
      if (opt.polyline) {
        pp.polyline = {
          positions: Cesium.Cartesian3.fromDegreesArray(positions),
          clampToGround: true,
          width: 2,
          material: Cesium.Color.fromCssColorString('rgba(213, 226, 246, 0.6)'),
          zIndex: 10
        }
      }
      if (opt.label) {
        pp.position = polyCenter
        pp.label = {
          text: pp.name,
          font: 'normal 20px MicroSoft YaHei',
          fillColor: new Cesium.Color.fromBytes(0, 0, 0, 255),
          backgroundColor: new Cesium.Color.fromBytes(255, 255, 255, 200),
          showBackground: true,
          scale: 1.0,
          backgroundPadding: new Cesium.Cartesian2(9, 7),
          outlineWidth: 0,
          pixelOffset: new Cesium.Cartesian2(20.0, -16.0),
          pixelOffsetScaleByDistance: new Cesium.NearFarScalar(100, 1.0, 2000, 0.7),
          style: Cesium.LabelStyle.FILL,
          horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
          verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
          scaleByDistance: new Cesium.NearFarScalar(500, 1.0, 2000, 0.7),
          disableDepthTestDistance: Number.POSITIVE_INFINITY
        }
      }
      dataSources.entities.add(pp);
    }
  })
}

/**标注**/
var AddMark = function (mark, OtherDataSource) {
  var option = {
    name: mark.name,
    type: mark.type,
    properties: mark.properties,
    position: Cesium.Cartesian3.fromDegrees(mark.longitude, mark.latitude, mark.height),
    billboard: {
      image: mark.icon,
      scale: mark.scale,
      scaleByDistance: new Cesium.NearFarScalar(100, 1.0, 5000, 0.5),
      disableDepthTestDistance: Number.POSITIVE_INFINITY,
      distanceDisplayCondition: new Cesium.DistanceDisplayCondition(10.0, 30000.0),
      // heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
    },
    label: {
      text: mark.name,
      font: 'normal 20px MicroSoft YaHei',
      fillColor: new Cesium.Color.fromBytes(0, 0, 0, 255),
      backgroundColor: new Cesium.Color.fromBytes(255, 255, 255, 200),
      showBackground: true,
      scale: mark.scale,
      backgroundPadding: new Cesium.Cartesian2(9, 7),
      outlineWidth: 0,
      pixelOffset: new Cesium.Cartesian2(20.0, -16.0),
      pixelOffsetScaleByDistance: new Cesium.NearFarScalar(100, 1.0, 2000, 0.6),
      style: Cesium.LabelStyle.FILL_AND_OUTLINE,
      horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
      verticalOrigin: Cesium.VerticalOrigin.TOP,
      scaleByDistance: new Cesium.NearFarScalar(500, 1.0, 3000, 0.6),
      disableDepthTestDistance: Number.POSITIVE_INFINITY,
      distanceDisplayCondition: new Cesium.DistanceDisplayCondition(10.0, 10000.0)
      // heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
      // show:false
    }
  }
  if (mark.distanceShow) {
    option.billboard.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(mark.distanceShow[0], mark.distanceShow[1])
    if (mark.distanceShow[0] < 10000) {
      option.label.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(mark.distanceShow[0], 10000)
    }
  }
  if (mark.id) {
    option.id = mark.id
  }
  if (mark.pixelOffset) {
    option.billboard.pixelOffset = new Cesium.Cartesian2(mark.pixelOffset[0], mark.pixelOffset[1])
  }
  if (mark.height < 10) {
    option.billboard.heightReference = Cesium.HeightReference.CLAMP_TO_GROUND
    option.label.heightReference = Cesium.HeightReference.CLAMP_TO_GROUND
  }
  var mark_ = OtherDataSource.entities.add(option)
  return mark_
}
/**标注**/
var AddMark2 = function (mark, OtherDataSource) {
  let x = 1;
  let flog = true;
  var option = {
    name: mark.name,
    type: mark.type,
    properties: mark.properties,
    position: Cesium.Cartesian3.fromDegrees(mark.longitude, mark.latitude, mark.height),
    billboard: {
      image: mark.icon,
      scale: mark.scale,
      scaleByDistance: new Cesium.NearFarScalar(100, 1.0, 2000, 0.6),
      disableDepthTestDistance: Number.POSITIVE_INFINITY,
      distanceDisplayCondition: new Cesium.DistanceDisplayCondition(10.0, 8000.0),
      scale: new Cesium.CallbackProperty(function () {
        if (flog) {
          x = x - 0.03;
          if (x <= 1.2) {
            flog = false;
          }
        } else {
          x = x + 0.03;
          if (x >= 1.8) {
            flog = true;
          }
        }
        return x;
      }, false)
      // heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
    },

  }
  if (mark.distanceShow) {
    option.billboard.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(mark.distanceShow[0], mark.distanceShow[1])
    if (mark.distanceShow[0] < 10000) {
      option.label.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(mark.distanceShow[0], 10000)
    }
  }
  if (mark.id) {
    option.id = mark.id
  }
  if (mark.pixelOffset) {
    option.billboard.pixelOffset = new Cesium.Cartesian2(mark.pixelOffset[0], mark.pixelOffset[1])
  }
  if (mark.height < 10 && option.billboard) {
    option.billboard.heightReference = Cesium.HeightReference.CLAMP_TO_GROUND
  }
  if (mark.height < 10 && option.label) {
    option.label.heightReference = Cesium.HeightReference.CLAMP_TO_GROUND
  }
  var mark_ = OtherDataSource.entities.add(option)
  return mark_
}
// ! 画点
var drawPoint = function (position, layer_, config_) {
  let config = config_ ? config_ : {}
  let layer = layer_ ? layer_ : viewer

  let colorAlpha = config.colorAlpha ? config.colorAlpha : 0.3
  if (config.colorAlpha == 0) {
    colorAlpha = 0
  }
  let color = config.color ?
    new Cesium.Color.fromCssColorString(config.color).withAlpha(colorAlpha) : Cesium.Color.SKYBLUE
  let outline_color = config.outline_color ?
    Cesium.Color.fromCssColorString(config.outline_color) : Cesium.Color.YELLOW
  let pointOption = {
    name: config.name ? config.name : "point_name",
    type: config.type ? config.type : "point_type",
    position: position,
    vertexIndex: config.vertexIndex ? config.vertexIndex : '',
    point: {
      pixelSize: config.pixelSize ? config.pixelSize : 10, // 点内大小
      color: color, // 点颜色
      outlineColor: outline_color, // 外框线颜色
      outlineWidth: config.outlineWidth ? config.outlineWidth : 3, // 外框线粗细
      disableDepthTestDistance: config.disableDepthTestDistance ? config.disableDepthTestDistance : Number.POSITIVE_INFINITY,
      heightReference: config.heightReference ? config.heightReference : Cesium.HeightReference.CLAMP_TO_GROUND,
    },
  };
  let point_ = layer.entities.add(pointOption);
  return point_
}
// ! 画线
var drawPolyline = function (positions, layer_, config_) {
  if (positions.length < 1) return;
  let config = config_ ? config_ : {}
  let layer = layer_ ? layer_ : viewer

  let colorAlpha = config.colorAlpha ? config.colorAlpha : 0.3
  if (config.colorAlpha == 0) {
    colorAlpha = 0
  }
  let color = config.color ?
    new Cesium.Color.fromCssColorString(config.color).withAlpha(colorAlpha) : Cesium.Color.GOLD
  let lineOption = {
    name: config.name ? config.name : "line_name",
    type: config.type ? config.type : "line_type",
    polyline: {
      positions: positions,
      width: config.width ? config.width : 5.0,
      material: color,
      depthFailMaterial: new Cesium.PolylineGlowMaterialProperty({
        color: color,
      }),
      clampToGround: true,
    },
  };
  if (obj.id) {
    option.id = obj.id
  }

  let line_ = layer.entities.add(lineOption)
  return line_
}
/**线**/
var AddLine = function (obj, OtherDataSource) {
  var color_ = obj.color ? Cesium.Color.fromCssColorString(obj.color) : Cesium.Color.YELLOW.withAlpha(0.5)
  var option = {
    name: obj.name ? obj.name : 'airline',
    type: obj.type ? obj.type : ''

  }
  if (obj.isheight) {
    option.polyline = {
      positions: Cesium.Cartesian3.fromDegreesArrayHeights(obj.positions),
      width: obj.width ? obj.width : 4,
      // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0.0, 30000.0),
      material: color_
    }
  } else {
    option.polyline = {
      positions: Cesium.Cartesian3.fromDegreesArray(obj.positions),
      width: obj.width ? obj.width : 4,
      material: color_,
      clampToGround: true
    }
  }

  if (obj.id) {
    option.id = obj.id
  }
  var p_ = OtherDataSource.entities.add(option)
  return p_
}
/**虚线**/
var AddDashLine = function (obj, OtherDataSource) {
  var color_ = obj.color ? Cesium.Color.fromCssColorString(obj.color) : Cesium.Color.YELLOW.withAlpha(0.5);
  var option = {
    name: obj.name ? obj.name : 'airline',
    type: obj.type ? obj.type : '',

  }
  // 区别实线和虚线
  const material = new Cesium.PolylineDashMaterialProperty({
    color: color_,
    // gapColor:Cesium.Color.WHITE,
    gapColor: Cesium.Color.fromCssColorString('rgba(255,255,255,0)'),
    // gapColor:obj.gep_color?obj.gep_color: ,
    dashLength: 5,
  })
  //
  if (obj.isheight) {
    option.polyline = {
      positions: Cesium.Cartesian3.fromDegreesArrayHeights(obj.positions),
      width: obj.width ? obj.width : 4,
      distanceDisplayCondition: new Cesium.DistanceDisplayCondition(10.0, 30000.0),
      material: material,
    }
  } else {
    option.polyline = {
      positions: Cesium.Cartesian3.fromDegreesArray(obj.positions),
      width: obj.width ? obj.width : 4,
      material: material,
      clampToGround: true,
    }
  }

  if (obj.id) {
    option.id = obj.id;
  }
  var p_ = OtherDataSource.entities.add(option);
  return p_;
}
// ! 画面
var drawPolygon = function (positions, layer_, config_) {
  if (positions.length < 3) return;
  let config = config_ ? config_ : {}
  let layer = layer_ ? layer_ : viewer


  let colorAlpha = config.colorAlpha ? config.colorAlpha : 0.3
  if (config.colorAlpha == 0) {
    colorAlpha = 0
  }
  let color = config.color ?
    new Cesium.Color.fromCssColorString(config.color).withAlpha(colorAlpha) : new Cesium.Color.fromCssColorString("#FFD700").withAlpha(0.2)
  let outline_color = config.outline_color ?
    Cesium.Color.fromCssColorString(config.outline_color) : Cesium.Color.YELLOW

  let polygonOption = {
    name: config.name ? config.name : "polygon_name",
    type: config.type ? config.type : "polygon_type",
    polygon: {
      hierarchy: positions,
      material: color
    },
  };
  let polygon_ = layer.entities.add(polygonOption)
  return polygon_
}

/**面
 var polygon = {
  id:'1111',
  type: 'dx',
  positions:arr2,
  extrudedHeight:120,
  color: 'rgba(200,2,2,0.5)'
};
 **/
var AddPolygon = function (obj, OtherDataSource) {
  var color_ = obj.color ? Cesium.Color.fromCssColorString(obj.color) : Cesium.Color.YELLOW.withAlpha(0.5)
  var option = {
    name: obj.name ? obj.name : 'polygon',
    type: obj.type ? obj.type : '',
    description: obj.description ? obj.description : ''
  }
  if (obj.clamp) {
    option.polygon = {
      hierarchy: {
        positions: Cesium.Cartesian3.fromDegreesArray(obj.positions)
      },
      material: color_,
      heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
    }
  } else {
    option.polygon = {
      hierarchy: {
        positions: Cesium.Cartesian3.fromDegreesArray(obj.positions)
      },
      height: obj.height ? obj.height : 1,
      extrudedHeight: obj.extrudedHeight ? obj.extrudedHeight : 0,
      perPositionHeight: obj.perPositionHeight ? obj.perPositionHeight : false,
      material: color_
    }
  }
  if (obj.label) {

    var arrs = obj.positions

    var positions = []
    var lon_sum = 0
    var lat_sum = 0

    for (var j = 0; j < arrs.length; j += 2) {
      lon_sum += arrs[j]
      lat_sum += arrs[j + 1]
    }
    var lon_center = lon_sum / arrs.length * 2
    var lat_center = lat_sum / arrs.length * 2
    option.position = Cesium.Cartesian3.fromDegrees(lon_center, lat_center, 10)
    option.label = {
      text: obj.name,
      font: 'normal 20px MicroSoft YaHei',
      fillColor: new Cesium.Color.fromBytes(0, 0, 0, 255),
      backgroundColor: new Cesium.Color.fromBytes(255, 255, 255, 200),
      showBackground: true,
      scale: 1.0,
      backgroundPadding: new Cesium.Cartesian2(9, 7),
      outlineWidth: 0,
      pixelOffset: new Cesium.Cartesian2(20.0, -16.0),
      pixelOffsetScaleByDistance: new Cesium.NearFarScalar(100, 1.0, 2000, 0.7),
      style: Cesium.LabelStyle.FILL,
      horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
      verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
      scaleByDistance: new Cesium.NearFarScalar(500, 1.0, 2000, 0.7),
      disableDepthTestDistance: Number.POSITIVE_INFINITY
    }
  }
  if (obj.id) {
    option.id = obj.id
  }
  var p_ = OtherDataSource.entities.add(option)
  return p_
}

// ! 画圆
var drawEllipse = function (position, layer_, config_) {
  let config = config_ ? config_ : {}
  let layer = layer_ ? layer_ : viewer
  let colorAlpha = config.colorAlpha ? config.colorAlpha : 0.3
  if (config.colorAlpha == 0) {
    colorAlpha = 0
  }
  let color = config.color ?
    new Cesium.Color.fromCssColorString(config.color).withAlpha(colorAlpha) : new Cesium.Color.fromCssColorString("#FFD700").withAlpha(0.3)
  let outline_color = config.outline_color ?
    Cesium.Color.fromCssColorString(config.outline_color) : Cesium.Color.BLUE
  let ellipseOption = {
    name: config.name ? config.name : "ellipse_name",
    type: config.type ? config.type : "ellipse_type",
    position: position,
    ellipse: {
      semiMinorAxis: config.radius,
      semiMajorAxis: config.radius,
      material: color,
      outline: true, // height must be set for outline to display
      outlineWidth: 4,
      outlineColor: outline_color
    },
  }
  if (config.height) {
    ellipseOption.ellipse.height = config.height
  }
  if (config.extrudedHeight) {
    ellipseOption.ellipse.extrudedHeight = config.extrudedHeight
  }
  if (config.distanceShow) {
    ellipseOption.ellipse.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(config.distanceShow[0], config.distanceShow[1])
  }
  if (config.id) {
    ellipseOption.id = config.id
  }
  let ellipse_ = layer.entities.add(ellipseOption);
  return ellipse_
}
var CreateFrustum = (function () {
  function _(obj, datasourceP) {
    this.options = {
      longitude: obj.longitude,
      latitude: obj.latitude,
      height: obj.height,
      heading: obj.heading ? obj.heading : 0,
      pitch: obj.pitch ? obj.pitch : -45,
      far: obj.far ? obj.far : 100,
      id: obj.id
    }
    this.layer = datasourceP
    this.primitive1 = null
    this.primitive2 = null
    this._init()
  }

  _.prototype._init = function () {
    var primitive1, primitive2
    var fov = 0.5,
      aspectRatio = 0.5

    var position_ = Cesium.Cartesian3.fromDegrees(this.options.longitude, this.options.latitude, this.options.height)
    var spotLightCamera = new Cesium.Camera(viewer.scene)

    spotLightCamera.setView({ // 设置视椎体的俯仰角度
      destination: position_,
      orientation: {
        heading: Cesium.Math.toRadians(this.options.heading),
        pitch: Cesium.Math.toRadians(this.options.pitch),
        roll: Cesium.Math.toRadians(0.0)
      }
    })

    var scratchRight = new Cesium.Cartesian3()
    var scratchRotation = new Cesium.Matrix3()
    var scratchOrientation = new Cesium.Quaternion()

    var position = spotLightCamera.positionWC
    var directions = spotLightCamera.directionWC
    var up = spotLightCamera.upWC
    var right = spotLightCamera.rightWC
    right = Cesium.Cartesian3.negate(right, scratchRight)

    var rotation = scratchRotation
    Cesium.Matrix3.setColumn(rotation, 0, right, rotation)
    Cesium.Matrix3.setColumn(rotation, 1, up, rotation)
    Cesium.Matrix3.setColumn(rotation, 2, directions, rotation)
    //计算视锥姿态
    var orientation = Cesium.Quaternion.fromRotationMatrix(rotation, scratchOrientation)

    var geometry1 = new Cesium.FrustumGeometry({
      frustum: new Cesium.PerspectiveFrustum({
        fov: Math.PI / 6 + fov,
        aspectRatio: 1 + aspectRatio,
        near: 1.0,
        far: this.options.far,
        xOffset: 0,
        yOffset: 0
      }),
      origin: position_,
      orientation: orientation
    })
    primitive1 = new Cesium.Primitive({
      geometryInstances: new Cesium.GeometryInstance({
        geometry: geometry1,
        attributes: {
          color: Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(0.0, 1.0, 1.0, 0.3)),
          show: new Cesium.ShowGeometryInstanceAttribute(true)
        },
        id: 'frustum_' + this.options.id
      }),
      appearance: new Cesium.PerInstanceColorAppearance({
        translucent: true,
        flat: true
      }),
      show: true,
      asynchronous: false
    })
    this.primitive1 = this.layer.add(primitive1)
    var geometry2 = new Cesium.FrustumOutlineGeometry({
      frustum: new Cesium.PerspectiveFrustum({
        fov: Math.PI / 6 + fov,
        aspectRatio: 1 + aspectRatio,
        near: 1.0,
        far: this.options.far,
        xOffset: 0,
        yOffset: 0
      }),
      origin: position_,
      orientation: orientation
    })
    primitive2 = new Cesium.Primitive({
      geometryInstances: new Cesium.GeometryInstance({
        geometry: geometry2,
        attributes: {
          color: Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(0.0, 1.0, 1.0, 1.0)),
          show: new Cesium.ShowGeometryInstanceAttribute(true)
        },
        id: 'frustum_' + this.options.id
      }),
      appearance: new Cesium.PerInstanceColorAppearance({
        translucent: true,
        flat: true
      }),
      show: true,
      asynchronous: false
    })
    this.primitive2 = this.layer.add(primitive2)
  }
  _.prototype.update = function (opt) {
    var color = opt.color

    var iid1 = 'frustum_' + this.options.id
    var attribute1 = this.primitive1.getGeometryInstanceAttributes(
      iid1
    )
    attribute1.color = Cesium.ColorGeometryInstanceAttribute.toValue(
      Cesium.Color.fromCssColorString(color).withAlpha(0.3)
    )
    var attribute2 = this.primitive2.getGeometryInstanceAttributes(
      iid1
    )
    attribute2.color = Cesium.ColorGeometryInstanceAttribute.toValue(
      Cesium.Color.fromCssColorString(color).withAlpha(1.0)
    )

  }
  _.prototype.removeAll = function () {
    this.layer.removeAll()
  }

  return _
})()
//  ! 文字
var drawText = function (position, layer_, config_) {
  let config = config_ || {}
  let layer = layer_ ? layer_ : viewer
  let textLength = -config.text.length * 30 / 2

  return layer.add({
    id: config.id,
    position: position,
    text: config.text,
    font: "normal 20px MicroSoft YaHei",
    fillColor: new Cesium.Color.fromBytes(0, 0, 0, 255),
    backgroundColor: new Cesium.Color.fromBytes(
      255,
      255,
      255,
      200
    ),
    showBackground: true,
    // scale: 0.1,
    backgroundPadding: new Cesium.Cartesian2(9, 7),
    outlineWidth: 0,
    pixelOffset: new Cesium.Cartesian2(0, -16.0),
    pixelOffsetScaleByDistance: new Cesium.NearFarScalar(
      100,
      1.0,
      2000,
      0.6
    ),
    style: Cesium.LabelStyle.FILL_AND_OUTLINE,
    horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
    verticalOrigin: Cesium.VerticalOrigin.TOP,
    scaleByDistance: new Cesium.NearFarScalar(
      500,
      1.0,
      3000,
      0.6
    ),
    disableDepthTestDistance: Number.POSITIVE_INFINITY,
    distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
      config.seeMin,
      config.seeMax
    ),
    heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
    show: false
  })
}

// ! 模型
var AddMyMap = async function (url) {
  return await new Promise(function (resolve, reject) {
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.onload = function () {
      //对两种类型的切片做适配，一种是ceiumlab 一种是gdal2tile
      if (this.readyState == 4 && this.status == 200) {
        var maplayer = new Cesium.UrlTemplateImageryProvider({
          url: url + '/{z}/{x}/{y}.png',
        });
        console.log('W走的是Url')
        maplayer = viewer.imageryLayers.addImageryProvider(maplayer);
        resolve(maplayer);
      } else {
        var maplayer = new Cesium.TileMapServiceImageryProvider({
          url: url,
          fileExtension: 'png'
        });
        console.log('W走的是Tile')
        maplayer = viewer.imageryLayers.addImageryProvider(maplayer);
        resolve(maplayer);
      }
    };
    xmlhttp.open("GET", url + "meta.json", true);
    xmlhttp.send();
  })
}
var RemoveMyMap = function (map) {
  viewer.imageryLayers.remove(map)
}


// ! 点击事件
var currentObjectId, currentPrimitive
var LeftClick = function (CLICK, flag) {
  var cartesian = viewer.scene.pickPosition(CLICK.position)
  if (CLICK) {
    var pick = viewer.scene.pick(CLICK.position)
  }

  var stopTime = Cesium.JulianDate.fromDate(new Date())
  viewer.clock.stopTime = stopTime.clone()
  var obj = {}
  if (cartesian) {
    var cartographic = Cesium.Cartographic.fromCartesian(cartesian)
    var currentClickLon = Cesium.Math.toDegrees(cartographic.longitude)
    var currentClickLat = Cesium.Math.toDegrees(cartographic.latitude)
    var currentClickHei = cartographic.height
    obj.longitude = currentClickLon
    obj.latitude = currentClickLat
    obj.height = currentClickHei
  }
  if (pick) {
    obj.pick = pick
    if (
      Cesium.defined(pick) &&
      Cesium.defined(pick.primitive) &&
      Cesium.defined(pick.id) &&
      Cesium.defined(pick.primitive.getGeometryInstanceAttributes)
    ) {
      if (!pick.id.id && flag) {
        if (currentObjectId) {
          var attributes = currentPrimitive.getGeometryInstanceAttributes(
            currentObjectId
          )
          if (attributes) {
            attributes.show = [1]
          }
        }
        currentObjectId = pick.id
        currentPrimitive = pick.primitive
        var attributes = currentPrimitive.getGeometryInstanceAttributes(
          currentObjectId
        )
        attributes.show = [0]
      }
    } else {
      if (currentObjectId) {
        var attributes = currentPrimitive.getGeometryInstanceAttributes(
          currentObjectId
        )
        if (attributes) {
          attributes.show = [1]
        }
      }
    }
  }
  return obj
}


var FlyToElementByGPS = function (obj) {
  var center = Cesium.Cartesian3.fromDegrees(obj.longitude, obj.latitude, obj.height)
  var heading = Cesium.Math.toRadians(obj.heading ? obj.heading : 0.0)
  var pitch = Cesium.Math.toRadians(obj.pitch ? obj.pitch : -40.0)
  var range = obj.distance ? obj.distance : 100
  // leftview参数用于设置 目标点在屏幕的左边
  if (obj.leftview) {
    console.log(obj.longitude)
    var newlon = parseFloat(range / 111000 / 3) + parseFloat(obj.longitude)
    console.log(newlon)
    center = Cesium.Cartesian3.fromDegrees(newlon, obj.latitude, obj.height)
  }
  // leftview2参数用于设置 目标点在屏幕的左边
  if (obj.leftview2) {
    var newlon = parseFloat(range / 111000 / 5) + parseFloat(obj.longitude)
    console.log(newlon)
    center = Cesium.Cartesian3.fromDegrees(newlon, obj.latitude, obj.height)
  }
  viewer.camera.flyToBoundingSphere(
    new Cesium.BoundingSphere(center, 50), {
      offset: new Cesium.HeadingPitchRange(heading, pitch, range),
      duration: 2,
      maximumHeight: 500,
      complete: obj.callback ? obj.callback : null
    }
  )
}
var ZoomToElementByGPS = function (obj) {
  var center = Cesium.Cartesian3.fromDegrees(obj.longitude, obj.latitude, obj.height)
  var heading = Cesium.Math.toRadians(0.0)
  var pitch = Cesium.Math.toRadians(-40.0)
  var range = obj.distance ? obj.distance : 100
  viewer.camera.viewBoundingSphere(
    new Cesium.BoundingSphere(center, 50),
    new Cesium.HeadingPitchRange(heading, pitch, range)
  )
  viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY)
}


var PathPrimitive = (function () {
  function _(positions, layer) {
    this.options = {
      polyline: {
        show: true,
        positions: [],
        material: Cesium.Color.YELLOW,
        width: 2,
        arcType: Cesium.ArcType.RHUMB
      }
    }
    this.layer = layer
    this.line = null
    this.positions = positions
    this._init()
  }

  _.prototype._init = function () {
    var _self = this;
    var _update = function () {
      return _self.positions
    }
    //实时更新polyline.positions
    this.options.polyline.positions = new Cesium.CallbackProperty(_update, false);
    this.line = this.layer.entities.add(this.options);
  }
  _.prototype.remove = function () {
    this.layer.entities.remove(this.line)
    for (let i in this) {
      delete this[i]
    }
  }
  return _
})()

var PlaneModel = (function () {
  function _(opt, layer) {
    this.options = {
      name: 'plane3d',
      orientation: opt.orientation,
      model: {
        uri: 'https://wukaileccmodel.oss-cn-shanghai.aliyuncs.com/cesium/plane3d.glb',
        minimumPixelSize: 32,
        maximumScale: 256,
        scale: 0.01
      }
    }
    this.layer = layer
    this.model = null
    this.position = opt.position
    this.orientation = opt.orientation
    console.log(111)
    this._init()
  }

  _.prototype.update = function (pos, orientation) {
    this.position = pos
    this.orientation = orientation
  }
  _.prototype._init = function () {
    var _self = this
    var _update = function () {
      return _self.position
    }
    var _update_heading = function () {
      return _self.orientation
    }
    //实时更新polyline.positions
    this.options.position = new Cesium.CallbackProperty(_update, false)
    this.options.orientation = new Cesium.CallbackProperty(_update_heading, false)

    this.model = this.layer.entities.add(this.options)
  }
  _.prototype.remove = function () {
    this.layer.entities.remove(this.model)
    for (let i in this) {
      delete this[i]
    }
  }
  return _
})()

/**
 * ! 超出后定点
 * @param {*} start 出发点
 * @param {*} end 结束点
 * @param {*} max 最大距离
 */
var exceedPoint = function (start, end, max) {
  // ? 获取角度
  let bearing = turf.bearing(
    turf.point(start),
    turf.point(end)
  );
  // ? 获取 溢出定点
  let point = getAnotherPoint(start[0], start[1], bearing, max);
  return [point.lng, point.lat]
}


// ! 根据经纬度和距离 获取另一个点
/**
 * lng 经度
 * lat 纬度
 * angle 角度
 * distance 距离
 */
var getAnotherPoint = function (lng, lat, angle, distance) {
  var a = 6378137;
  var b = 6356752.3142;
  var f = 1 / 298.257223563;

  var alpha1 = angle * (Math.PI / 180);
  var sinAlpha1 = Math.sin(alpha1);
  var cosAlpha1 = Math.cos(alpha1);
  var tanU1 = (1 - f) * Math.tan(lat * (Math.PI / 180));
  var cosU1 = 1 / Math.sqrt(1 + tanU1 * tanU1),
    sinU1 = tanU1 * cosU1;
  var sigma1 = Math.atan2(tanU1, cosAlpha1);
  var sinAlpha = cosU1 * sinAlpha1;
  var cosSqAlpha = 1 - sinAlpha * sinAlpha;
  var uSq = (cosSqAlpha * (a * a - b * b)) / (b * b);
  var A =
    1 + (uSq / 16384) * (4096 + uSq * (-768 + uSq * (20 - 175 * uSq)));
  var B = (uSq / 1024) * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
  var sigma = distance / (b * A),
    sigmaP = 2 * Math.PI;
  while (Math.abs(sigma - sigmaP) > 1e-12) {
    var cos2SigmaM = Math.cos(2 * sigma1 + sigma);
    var sinSigma = Math.sin(sigma);
    var cosSigma = Math.cos(sigma);
    var deltaSigma =
      B *
      sinSigma *
      (cos2SigmaM +
        (B / 4) *
        (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) -
          (B / 6) *
          cos2SigmaM *
          (-3 + 4 * sinSigma * sinSigma) *
          (-3 + 4 * cos2SigmaM + cos2SigmaM)));
    sigmaP = sigma;
    sigma = distance / (b * A) + deltaSigma;
  }
  var tmp = sinU1 * sinSigma - cosU1 * cosSigma * cosAlpha1;
  var lat2 = Math.atan2(
    sinU1 * cosSigma + cosU1 * sinSigma * cosAlpha1,
    (1 - f) * Math.sqrt(sinAlpha * sinAlpha + tmp * tmp)
  );
  var lambda = Math.atan2(
    sinSigma * sinAlpha1,
    cosU1 * cosSigma - sinU1 * sinSigma * cosAlpha1
  );
  var C = (f / 16) * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));
  var L =
    lambda -
    (1 - C) *
    f *
    sinAlpha *
    (sigma +
      C *
      sinSigma *
      (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));

  return {
    lng: Number(lng) + L * (180 / Math.PI),
    lat: lat2 * (180 / Math.PI),
  };
}

// ! 画 线外扩
var drawLineBuffer = function (positions, width, layer) {
  let line = turf.lineString(positions);
  let buffered = turf.buffer(line, width, {
    units: "meters"
  });
  let points = buffered.geometry.coordinates[0];
  let degreesArray = pointsToDegreesArray(points);
  return addBufferPolygon(Cesium.Cartesian3.fromDegreesArray(degreesArray), layer);
}
// ? 添加缓冲面
var addBufferPolygon = function (positions, layer_) {
  let layer = layer_ ? layer_ : viewer
  return layer.entities.add({
    name: "缓冲面",
    polygon: {
      hierarchy: new Cesium.PolygonHierarchy(positions),
      material: Cesium.Color.fromCssColorString("#0000FF").withAlpha(0.3),
      classificationType: Cesium.ClassificationType.BOTH,
    },
  });
}
// ? 格式转换
var pointsToDegreesArray = function (points) {
  let degreesArray = [];
  points.map((item) => {
    degreesArray.push(item[0]);
    degreesArray.push(item[1]);
  });
  return degreesArray;
}


// 多面 显示
var MultiPolygon = (function () {
  function _(obj, layer) {
    this.shape = obj.geometry
    this.name = obj.name ? obj.name : '未命名'
    this.id = obj.id ? obj.id : null
    this.type = obj.type ? obj.type : null
    this.lon_center = obj.lon_center ? obj.lon_center : null
    this.lat_center = obj.lat_center ? obj.lat_center : null
    this.layer = layer
    this.label = obj.label ? obj.label : null
    this.color = obj.color ? Cesium.Color.fromCssColorString(obj.color) : Cesium.Color.YELLOW.withAlpha(0.5)
    this.description = obj.description ? obj.description : '',
      this.polygons = []
    this.holes = []
    this.entities = []
    this._init()
  }

  _.prototype._init = function () {
    var _self = this
    var coordinates = this.shape.coordinates

    for (var i = 0; i < coordinates.length; i++) {

      for (var j = 0; j < coordinates[i].length; j++) {
        var arr = []
        for (var k = 0; k < coordinates[i][j].length; k++) {
          arr.push(coordinates[i][j][k][0], coordinates[i][j][k][1])
        }
        if (j == 0) {
          this.polygons.push(arr)
        } else {

        }
      }

    }
    for (var i = 0; i < this.polygons.length; i++) {
      var polygon = {
        polygon: {
          hierarchy: {
            positions: Cesium.Cartesian3.fromDegreesArray(this.polygons[i])
          },
          material: this.color,
          heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
        },
        id: this.id + '_' + i,
        name: this.name,
        type: this.type

      }
      var enty = this.layer.entities.add(polygon)
      if (i == 0) {

        if (this.label && this.lon_center && this.lat_center) {

          var lon_center = this.lon_center
          var lat_center = this.lat_center

          if (this.height) {
            var e_height = this.height
          } else if (this.extrudedHeight) {
            var e_height = this.extrudedHeight
          } else {
            var e_height = 10
          }

          enty.position = Cesium.Cartesian3.fromDegrees(lon_center, lat_center, e_height),
            enty.label = {
              text: this.label,
              font: 'normal 20px MicroSoft YaHei',
              fillColor: new Cesium.Color.fromBytes(0, 0, 0, 255),
              backgroundColor: new Cesium.Color.fromBytes(255, 255, 255, 200),
              showBackground: true,
              scale: 1.0,
              backgroundPadding: new Cesium.Cartesian2(9, 7),
              outlineWidth: 0,
              pixelOffset: new Cesium.Cartesian2(20.0, -16.0),
              pixelOffsetScaleByDistance: new Cesium.NearFarScalar(100, 1.0, 2000, 0.7),
              style: Cesium.LabelStyle.FILL,
              horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
              verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
              scaleByDistance: new Cesium.NearFarScalar(500, 1.0, 2000, 0.7),
              disableDepthTestDistance: Number.POSITIVE_INFINITY
            }
        }
      }

      this.entities.push(enty)
    }

  }
  _.prototype.remove = function () {
    for (var i = 0; i < this.entities.length; i++) {
      this.layer.entities.remove(this.entities[i])
    }

    for (let i in this) {
      delete this[i]
    }
  }
  return _
})()

// 多面 挖空
var MultiPolygonDecrease = (function () {
  function _(obj, layer) {
    this.shape = obj.geometry
    this.name = obj.name ? obj.name : '未命名'
    this.id = obj.id ? obj.id : null
    this.type = obj.type ? obj.type : null
    this.lon_center = obj.lon_center ? obj.lon_center : null
    this.lat_center = obj.lat_center ? obj.lat_center : null
    this.layer = layer
    this.label = obj.label ? obj.label : null
    this.color = obj.color ? Cesium.Color.fromCssColorString(obj.color) : Cesium.Color.YELLOW.withAlpha(0.5)
    this.description = obj.description ? obj.description : '',
      this.polygons = []
    this.holes = []
    this.entities = []

    console.log('MultiPolygon')
    this._init()
  }

  _.prototype._init = function () {
    var _self = this
    var coordinates = this.shape.coordinates

    for (var i = 0; i < coordinates.length; i++) {

      for (var j = 0; j < coordinates[i].length; j++) {
        var arr = []
        for (var k = 0; k < coordinates[i][j].length; k++) {
          arr.push(coordinates[i][j][k][0], coordinates[i][j][k][1])
        }
        if (i == 0) {
          this.polygons.push(arr)
        } else {
          if (j == 0) {
            let hole = {
              positions: Cesium.Cartesian3.fromDegreesArray(arr)
            }
            this.holes.push(hole)
          }
        }
      }

    }
    for (var i = 0; i < this.polygons.length; i++) {
      var polygon = {
        polygon: {
          hierarchy: {
            positions: Cesium.Cartesian3.fromDegreesArray(this.polygons[i])
          },
          material: this.color,
          heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
        },
        id: this.id + '_' + i,
        name: this.name,
        type: this.type

      }
      if (i == 0) {
        //  镂空
        polygon.polygon.hierarchy.holes = this.holes
      }
      var enty = this.layer.entities.add(polygon)
      if (this.label && this.lon_center && this.lat_center) {

        var lon_center = this.lon_center
        var lat_center = this.lat_center

        if (this.height) {
          var e_height = this.height
        } else if (this.extrudedHeight) {
          var e_height = this.extrudedHeight
        } else {
          var e_height = 10
        }

        enty.position = Cesium.Cartesian3.fromDegrees(lon_center, lat_center, e_height),
          enty.label = {
            text: this.label,
            font: 'normal 20px MicroSoft YaHei',
            fillColor: new Cesium.Color.fromBytes(0, 0, 0, 255),
            backgroundColor: new Cesium.Color.fromBytes(255, 255, 255, 200),
            showBackground: true,
            scale: 1.0,
            backgroundPadding: new Cesium.Cartesian2(9, 7),
            outlineWidth: 0,
            pixelOffset: new Cesium.Cartesian2(20.0, -16.0),
            pixelOffsetScaleByDistance: new Cesium.NearFarScalar(100, 1.0, 2000, 0.7),
            style: Cesium.LabelStyle.FILL,
            horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
            scaleByDistance: new Cesium.NearFarScalar(500, 1.0, 2000, 0.7),
            disableDepthTestDistance: Number.POSITIVE_INFINITY
          }
      }

      this.entities.push(enty)
    }

  }
  _.prototype.remove = function () {
    for (var i = 0; i < this.entities.length; i++) {
      this.layer.entities.remove(this.entities[i])
    }

    for (let i in this) {
      delete this[i]
    }
  }
  return _
})()


export {
  InitMap,
  cartesian3ToLatLng,
  cartesian2ToCartesian3,
  cartesian2ToLatLng,
  CreateLayer,
  BillBoardCollectionLayer,
  LayerRemoveAll,
  LoadCityROI,
  LoadGeoJsonPolygon,
  AddMark,
  AddMark2,
  drawPoint,
  drawPolyline,
  AddLine,
  AddDashLine,
  drawPolygon,
  AddPolygon,
  drawEllipse,
  CreateFrustum,
  drawText,
  AddMyMap,
  RemoveMyMap,
  LeftClick,
  FlyToElementByGPS,
  ZoomToElementByGPS,
  PathPrimitive,
  PlaneModel,
  exceedPoint,
  getAnotherPoint,
  drawLineBuffer,
  MultiPolygon,
  MultiPolygonDecrease
}
